#ifndef RTE_OS_PLC_RTE_ABI_H
#define RTE_OS_PLC_RTE_ABI_H

#include "plc_wamp.h"

// #if defined(MODBUS_TCP) || defined(MODBUS_RTU)

#include "plc_modbus.h"

// #endif

#ifdef USE_MC
#include <MotionKernel.h>
#include "MotionFB_Def.h"
#endif

#ifdef USE_SOEM
#include "soem.h"
#endif

typedef uint32_t uint32_t;
typedef unsigned short u16;
typedef unsigned char u8;
typedef int32_t s32;
typedef unsigned long long u64;

typedef struct {
#ifdef USE_MC
    int (*motion_init)(unsigned long long);

    void (*motion_cleanup)(void);

    void (*motion_retrieve)(void);

    void (*motion_publish)(void);

    void (*motion_setperiod)(uint64_t common_ticktime);

    // motion function block api
    void (*__mcl_cmd_MC_Power)(MC_POWER *data__);

    void (*__mcl_cmd_MC_Home)(MC_HOME *data__);

    void (*__mcl_cmd_MC_Stop)(MC_STOP *data__);

    void (*__mcl_cmd_MC_Halt)(MC_HALT *data__);

    void (*__mcl_cmd_MC_MoveAbsolute)(MC_MOVEABSOLUTE *data__);

    void (*__mcl_cmd_MC_MoveRelative)(MC_MOVERELATIVE *data__);

    void (*__mcl_cmd_MC_MoveAdditive)(MC_MOVEADDITIVE *data__);

    void (*__mcl_cmd_MC_ReadParameter)(MC_READPARAMETER *data__);

    void (*__mcl_cmd_MC_ReadBoolParameter)(MC_READBOOLPARAMETER *data__);

    void (*__mcl_cmd_MC_WriteParameter)(MC_WRITEPARAMETER *data__);

    void (*__mcl_cmd_MC_WriteBoolParameter)(MC_WRITEBOOLPARAMETER *data__);

    void (*__mcl_cmd_MC_ReadStatus)(MC_READSTATUS *data__);

    void (*__mcl_cmd_MC_ReadAxisInfo)(MC_READAXISINFO *data__);

    void (*__mcl_cmd_MC_ReadAxisError)(MC_READAXISERROR *data__);

    void (*__mcl_cmd_MC_Reset)(MC_RESET *data__);

    void (*__mcl_cmd_MC_GetTorqueLimit)(MC_GETTORQUELIMIT *);

    void (*__mcl_cmd_MC_SetTorqueLimit)(MC_SETTORQUELIMIT *);

    void (*__mcl_cmd_MC_MoveSuperimposed)(MC_MOVESUPERIMPOSED *);

    void (*__mcl_cmd_MC_HaltSuperimposed)(MC_HALTSUPERIMPOSED *);

    void (*__mcl_cmd_MC_MoveVelocity)(MC_MOVEVELOCITY *);

    void (*__mcl_cmd_MC_MoveContinuousAbsolute)(MC_MOVECONTINUOUSABSOLUTE *);

    void (*__mcl_cmd_MC_MoveContinuousRelative)(MC_MOVECONTINUOUSRELATIVE *);

    void (*__mcl_cmd_MC_TorqueControl)(MC_TORQUECONTROL *);

    void (*__mcl_cmd_MC_PositionProfile)(MC_POSITIONPROFILE *);

    void (*__mcl_cmd_MC_VelocityProfile)(MC_VELOCITYPROFILE *);

    void (*__mcl_cmd_MC_AccelerationProfile)(MC_ACCELERATIONPROFILE *);

    void (*__mcl_cmd_MC_SetPosition)(MC_SETPOSITION *);

    void (*__mcl_cmd_MC_SetOverride)(MC_SETOVERRIDE *);

    void (*__mcl_cmd_MC_ReadDigitalInput)(MC_READDIGITALINPUT *);

    void (*__mcl_cmd_MC_ReadDigitalOutput)(MC_READDIGITALOUTPUT *);

    void (*__mcl_cmd_MC_WriteDigitalOutput)(MC_WRITEDIGITALOUTPUT *);

    void (*__mcl_cmd_MC_ReadActualPosition)(MC_READACTUALPOSITION *);

    void (*__mcl_cmd_MC_ReadActualVelocity)(MC_READACTUALVELOCITY *);

    void (*__mcl_cmd_MC_ReadActualTorque)(MC_READACTUALTORQUE *);

    void (*__mcl_cmd_MC_ReadMotionState)(MC_READMOTIONSTATE *);

    void (*__mcl_cmd_MC_DigitalCamSwitch)(MC_DIGITALCAMSWITCH *);

    void (*__mcl_cmd_MC_TouchProbe)(MC_TOUCHPROBE *);

    void (*__mcl_cmd_MC_AbortTrigger)(MC_ABORTTRIGGER *);

    void (*__mcl_cmd_MC_CamTableSelect)(MC_CAMTABLESELECT *);

    void (*__mcl_cmd_MC_CamIn)(MC_CAMIN *);

    void (*__mcl_cmd_MC_CamOut)(MC_CAMOUT *);

    void (*__mcl_cmd_MC_GearIn)(MC_GEARIN *);

    void (*__mcl_cmd_MC_GearOut)(MC_GEAROUT *);

    void (*__mcl_cmd_MC_GearInPos)(MC_GEARINPOS *);

    void (*__mcl_cmd_MC_PhasingAbsolute)(MC_PHASINGABSOLUTE *);

    void (*__mcl_cmd_MC_PhasingRelative)(MC_PHASINGRELATIVE *);

    void (*__mcl_cmd_MC_CombineAxes)(MC_COMBINEAXES *);

    u8 (*__MK_CheckPublic_MC_CAM_REF)(int);

    int (*__MK_Alloc_MC_CAM_ID)();

    int (*__MK_Alloc_AXIS_REF)();

    int (*__MK_Alloc_MC_TRIGGER_REF)();

    uint8_t *(*__MK_GetPublic_MC_TRIGGER_REF)(int);

    int (*__MK_Alloc_MC_OUTPUT_REF)();

    uint32_t *(*__MK_GetPublic_MC_OUTPUT_REF)(int);

    int (*__MK_Alloc_MC_TP_REF)();

    u8 (*__MK_CheckPublic_MC_TP_REF)(int);

    int (*__MK_Alloc_MC_TV_REF)();

    u8 (*__MK_CheckPublic_MC_TV_REF)(int);

    int (*__MK_Alloc_MC_TA_REF)();

    u8 (*__MK_CheckPublic_MC_TA_REF)(int);

    int (*__MK_Alloc_MC_CAMSWITCH_REF)();

    u8 (*__MK_CheckPublic_MC_CAMSWITCH_REF)(int);

    int (*__MK_Alloc_MC_CAM_REF)();
    int (*MK_Load_MC_TP_REF_CSV)(int);
    int (*MK_Load_MC_TV_REF_CSV)(int);
    int (*MK_Load_MC_TA_REF_CSV)(int);
    int (*MK_Load_MC_CAMSWITCH_REF_CSV)(int);
    int (*MK_Load_MC_CAM_REF_CSV)(int);
#endif
} motion_t;

#include "dgus_abi.h"
/*
 * @brief EtherCAT Master 接口定义
 */
#include "ecrt.h"

#include "remote.h"
#include "soem.h"

#include "display.h"
#include "canopen.h"

typedef struct {
    /*
     * 初始化
     */
    int (*init)(int argc, char **argv);

    /*
     * 获取数据
     */
    void (*retrieve)();

    /*
     * 发布数据
     */
    void (*publish)();

    /*
     * @brief cleanup
     */
    void (*cleanup)();

#ifdef USE_IGH

    int (*ecrt_domain_reg_pdo_entry_list)(
        ec_domain_t *domain,                     /**< Domain. */
        const ec_pdo_entry_reg_t *pdo_entry_regs /**< Array of PDO
                                               registrations. */
    );

    int (*ecrt_master_set_send_interval)(
        ec_master_t *master, /**< EtherCAT master. */
        size_t send_interval /**< Send interval in us */
    );

    int (*ecrt_master_activate)(
        ec_master_t *master /**< EtherCAT master. */
    );

    u8 *(*ecrt_domain_data)(
        ec_domain_t *domain /**< Domain. */
    );

    void (*ecrt_release_master)(
        ec_master_t *master /**< EtherCAT master */
    );

    ec_slave_config_t *(*ecrt_master_slave_config)(
        ec_master_t *master, /**< EtherCAT master */
        uint16_t alias,      /**< Slave alias. */
        uint16_t position,   /**< Slave position. */
        uint32_t vendor_id,       /**< Expected vendor ID. */
        uint32_t product_code     /**< Expected product code. */
    );

    int (*ecrt_slave_config_pdos)(
        ec_slave_config_t *sc,       /**< Slave configuration. */
        unsigned int n_syncs,        /**< Number of sync manager configurations in
                            \a syncs. */
        const ec_sync_info_t syncs[] /**< Array of sync manager
                                   configurations. */
    );

#endif
} ect_t;

typedef struct {
    const char *(*read_key)(const char *);

    int (*write_key)(const char *, const char *);
} kvdb_rte_t;


typedef struct {
    u64 (*get_time)(); // 获取当前时间

    void (*set_timer)(unsigned long long, unsigned long long); // 设置PLC运行周期
    void (*InitRetain)();                                      // 启动retain

    int (*check_retain_buf)(); // 校验retain数据

    void (*invalidate_retain_buf)(); // 禁止retain

    void (*validate_retain_buf)(); // 使能retain

    void (*retain)(unsigned int, unsigned int, void *); // 执行retain

    void (*remind)(unsigned int, unsigned int, void *); // 读取retain数据

    int (*retain_close)(); // 关闭retain

    u8 (*input)(u8, u8, u8, u8, u8); // 读取开关量输入,高速任务使用

    void (*output)(u8, u8, u8, u8, u8, u8); // 设置开关量输出,高速任务使用

    uint32_t (*log_cnt_get)(u8); // 获取log记录数量

    uint32_t (*log_msg_get)(u8, uint32_t, char *, uint32_t, uint32_t *, uint32_t *, uint32_t *); // 读取log记录

    void (*log_cnt_reset)(); // 复位log计数

    uint32_t (*timestamp)(); // 获取当前时间(从零开始的ms数)

    void (*SerialBegin)(u8 serialno, int baud); // 启动串口

    int (*SerialRead)(u8 serialno); // 串口读一个字节

    int (*SerialWrite)(u8 serialno, u8 *buf, u8 len); // 串口写

    int (*SerialAvailable)(u8 serialno); // 串口是否有数据

    void (*delay)(uint32_t); // 延时

    int (*create_task)(const char *, uint32_t time, void *cb); // 创建普通任务

    int (*create_timer_task)(const char *, u8 id, uint32_t time, void *cb); // 创建定时器任务

    int (*create_exti_task)(const char *, u8 id, u8 rise, u8 fall, void *cb); // 创建IO中断任务

    int (*log_info)(const char *format, ...); // log接口

    int (*log_debug)(const char *format, ...);

    int (*log_warning)(const char *format, ...);

    int (*log_error)(const char *format, ...);

    // #if defined(MODBUS_TCP) || defined(MODBUS_RTU)
    const mb_abi_t *mb_abi; // MODBUS操作接口
    const mb_request_abi_t *mb_request_abi;
    const mb_master_abi_t *mb_master_abi;
    const mb_slave_abi_t *mb_slave_abi;
    // #endif
    const motion_t *mc;
    wamp_t *iot; // IOT接口

    void *(*create_thread)(const char *name, uint32_t stack_size, int poriority, void *func, const void *arg); // 创建线程
    const kvdb_rte_t *kvdb;
    /*
     * @brief EtherCAT Master接口
     */
    ect_t *ect;
    const soem_t *soem;
    const display_abi *display;
    const dgus_abi *dgus;
    const remote_abi *remote;

    int (*send_email)(const char *subject, const char *message, const char *filename);

    int (*tsl_save)(u8 db_index, const char *bytes, int len);

    int (*read_file)(const char *filename, char *buf, int len);

    int (*write_file)(const char *filename, const char *buf, int len);

    int (*remove_file)(const char *filename);

    int (*sd_read_file)(const char *filename, char *buf, int len);

    int (*lfs2sd_copy)(const char *src, const char *dst);

    int (*sd2lfs_copy)(const char *src, const char *dst);

    int (*loadui)(void *ui);

    void (*hmi_set_win)(int index);

    void (*hmi_add_assert)(const void *assert);

    canopen_abi_t *canopen;
    void *var;
    void *var_buf; // PLC变量内存区
} plc_rte_abi_t;
extern const plc_rte_abi_t *plc_rte;
extern const plc_rte_abi_t rte_var;
#endif // RTE_OS_PLC_RTE_ABI_H
